#!/bin/bash

# Holter Trode Deployment Script
# This script deploys trodes to remote nodes with bootstrap support

set -euo pipefail

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
HOLTER_DIR="$(dirname "$SCRIPT_DIR")"
LOG_FILE="/tmp/holter-deploy.log"
DEFAULT_TRODE_PORT=8080
DEFAULT_REMOTE_DIR="/opt/holter"

# Logging functions
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1" | tee -a "$LOG_FILE"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1" | tee -a "$LOG_FILE"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1" | tee -a "$LOG_FILE"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1" | tee -a "$LOG_FILE"
}

# Help function
show_help() {
    cat << EOF
Holter Trode Deployment Script

Usage: $0 [OPTIONS] COMMAND [ARGS]

Commands:
    deploy-node NODE_ID [PORT]     Deploy trode to a specific node
    deploy-all [START_PORT]        Deploy trodes to all nodes
    bootstrap-node NODE_ID         Bootstrap a specific node only
    bootstrap-all                  Bootstrap all nodes only
    stop-node NODE_ID [PORT]       Stop trode on a specific node
    restart-node NODE_ID [PORT]    Restart trode on a specific node
    status-node NODE_ID [PORT]     Check trode status on a specific node
    logs-node NODE_ID [PORT] [LINES] Get trode logs from a specific node
    list-nodes                     List all nodes in database
    build-trode                    Build the trode binary
    test-connection NODE_ID        Test SSH connection to a node

Options:
    -h, --help                     Show this help message
    -v, --verbose                  Enable verbose output
    -f, --force                    Force deployment even if already deployed
    -d, --dry-run                  Show what would be done without executing
    --log-file FILE                Specify log file (default: $LOG_FILE)

Examples:
    $0 deploy-node 1 8080          # Deploy trode to node 1 on port 8080
    $0 deploy-all 8080             # Deploy trodes to all nodes starting from port 8080
    $0 bootstrap-node 1            # Bootstrap node 1 only
    $0 status-node 1 8080          # Check status of trode on node 1
    $0 logs-node 1 8080 50         # Get last 50 lines of logs from node 1

EOF
}

# Check prerequisites
check_prerequisites() {
    log_info "Checking prerequisites..."
    
    # Check if Go is installed
    if ! command -v go &> /dev/null; then
        log_error "Go is not installed. Please install Go first."
        exit 1
    fi
    
    # Check if we're in the right directory
    if [[ ! -f "$HOLTER_DIR/go.mod" ]]; then
        log_error "Not in a Go module directory. Please run from the holter project root."
        exit 1
    fi
    
    # Check if database exists
    if [[ ! -f "$HOLTER_DIR/monitor/holter.db" ]]; then
        log_error "Database not found. Please run the migration first: cd monitor && go run . migrate"
        exit 1
    fi
    
    log_success "Prerequisites check passed"
}

# Build trode binary
build_trode() {
    log_info "Building trode binary..."
    
    cd "$HOLTER_DIR/trode"
    
    if [[ ! -f "go.mod" ]]; then
        log_error "Trode directory not found or not a Go module"
        exit 1
    fi
    
    # Clean and build
    go clean
    go build -o trode .
    
    if [[ ! -f "trode" ]]; then
        log_error "Failed to build trode binary"
        exit 1
    fi
    
    log_success "Trode binary built successfully"
    cd "$HOLTER_DIR"
}

# Deploy to a specific node
deploy_node() {
    local node_id="$1"
    local port="${2:-$DEFAULT_TRODE_PORT}"
    
    log_info "Deploying trode to node $node_id on port $port"
    
    cd "$HOLTER_DIR/monitor"
    
    # Run deployment
    if go run . deploy-node "$node_id" "$port"; then
        log_success "Successfully deployed trode to node $node_id"
    else
        log_error "Failed to deploy trode to node $node_id"
        exit 1
    fi
}

# Deploy to all nodes
deploy_all() {
    local start_port="${1:-$DEFAULT_TRODE_PORT}"
    
    log_info "Deploying trodes to all nodes starting from port $start_port"
    
    cd "$HOLTER_DIR/monitor"
    
    # Run deployment
    if go run . deploy-all "$start_port"; then
        log_success "Successfully deployed trodes to all nodes"
    else
        log_error "Failed to deploy trodes to all nodes"
        exit 1
    fi
}

# Bootstrap a specific node
bootstrap_node() {
    local node_id="$1"
    
    log_info "Bootstrapping node $node_id"
    
    cd "$HOLTER_DIR/monitor"
    
    # Run bootstrap
    if go run . bootstrap-node "$node_id"; then
        log_success "Successfully bootstrapped node $node_id"
    else
        log_error "Failed to bootstrap node $node_id"
        exit 1
    fi
}

# Bootstrap all nodes
bootstrap_all() {
    log_info "Bootstrapping all nodes"
    
    cd "$HOLTER_DIR/monitor"
    
    # Run bootstrap
    if go run . bootstrap-all; then
        log_success "Successfully bootstrapped all nodes"
    else
        log_error "Failed to bootstrap all nodes"
        exit 1
    fi
}

# Stop trode on a specific node
stop_node() {
    local node_id="$1"
    local port="${2:-$DEFAULT_TRODE_PORT}"
    
    log_info "Stopping trode on node $node_id (port $port)"
    
    cd "$HOLTER_DIR/monitor"
    
    # Run stop command
    if go run . stop-node "$node_id" "$port"; then
        log_success "Successfully stopped trode on node $node_id"
    else
        log_error "Failed to stop trode on node $node_id"
        exit 1
    fi
}

# Restart trode on a specific node
restart_node() {
    local node_id="$1"
    local port="${2:-$DEFAULT_TRODE_PORT}"
    
    log_info "Restarting trode on node $node_id (port $port)"
    
    cd "$HOLTER_DIR/monitor"
    
    # Run restart command
    if go run . restart-node "$node_id" "$port"; then
        log_success "Successfully restarted trode on node $node_id"
    else
        log_error "Failed to restart trode on node $node_id"
        exit 1
    fi
}

# Check trode status on a specific node
status_node() {
    local node_id="$1"
    local port="${2:-$DEFAULT_TRODE_PORT}"
    
    log_info "Checking trode status on node $node_id (port $port)"
    
    cd "$HOLTER_DIR/monitor"
    
    # Run status command
    if go run . status-node "$node_id" "$port"; then
        log_success "Trode is running on node $node_id"
    else
        log_warning "Trode is not running on node $node_id"
    fi
}

# Get trode logs from a specific node
logs_node() {
    local node_id="$1"
    local port="${2:-$DEFAULT_TRODE_PORT}"
    local lines="${3:-50}"
    
    log_info "Getting trode logs from node $node_id (port $port, last $lines lines)"
    
    cd "$HOLTER_DIR/monitor"
    
    # Run logs command
    go run . logs-node "$node_id" "$port" "$lines"
}

# List all nodes
list_nodes() {
    log_info "Listing all nodes"
    
    cd "$HOLTER_DIR/monitor"
    
    # Run list command
    go run . list-nodes
}

# Test SSH connection to a node
test_connection() {
    local node_id="$1"
    
    log_info "Testing SSH connection to node $node_id"
    
    cd "$HOLTER_DIR/monitor"
    
    # Run test command
    if go run . test-connection "$node_id"; then
        log_success "SSH connection to node $node_id is working"
    else
        log_error "SSH connection to node $node_id failed"
        exit 1
    fi
}

# Main function
main() {
    # Parse command line arguments
    local verbose=false
    local force=false
    local dry_run=false
    
    while [[ $# -gt 0 ]]; do
        case $1 in
            -h|--help)
                show_help
                exit 0
                ;;
            -v|--verbose)
                verbose=true
                shift
                ;;
            -f|--force)
                force=true
                shift
                ;;
            -d|--dry-run)
                dry_run=true
                shift
                ;;
            --log-file)
                LOG_FILE="$2"
                shift 2
                ;;
            *)
                break
                ;;
        esac
    done
    
    # Set up logging
    touch "$LOG_FILE"
    log_info "Starting Holter deployment script"
    log_info "Log file: $LOG_FILE"
    
    if [[ $# -eq 0 ]]; then
        log_error "No command specified"
        show_help
        exit 1
    fi
    
    local command="$1"
    shift
    
    # Check prerequisites
    check_prerequisites
    
    # Execute command
    case "$command" in
        deploy-node)
            if [[ $# -lt 1 ]]; then
                log_error "deploy-node requires a node ID"
                exit 1
            fi
            deploy_node "$@"
            ;;
        deploy-all)
            deploy_all "$@"
            ;;
        bootstrap-node)
            if [[ $# -lt 1 ]]; then
                log_error "bootstrap-node requires a node ID"
                exit 1
            fi
            bootstrap_node "$@"
            ;;
        bootstrap-all)
            bootstrap_all
            ;;
        stop-node)
            if [[ $# -lt 1 ]]; then
                log_error "stop-node requires a node ID"
                exit 1
            fi
            stop_node "$@"
            ;;
        restart-node)
            if [[ $# -lt 1 ]]; then
                log_error "restart-node requires a node ID"
                exit 1
            fi
            restart_node "$@"
            ;;
        status-node)
            if [[ $# -lt 1 ]]; then
                log_error "status-node requires a node ID"
                exit 1
            fi
            status_node "$@"
            ;;
        logs-node)
            if [[ $# -lt 1 ]]; then
                log_error "logs-node requires a node ID"
                exit 1
            fi
            logs_node "$@"
            ;;
        list-nodes)
            list_nodes
            ;;
        build-trode)
            build_trode
            ;;
        test-connection)
            if [[ $# -lt 1 ]]; then
                log_error "test-connection requires a node ID"
                exit 1
            fi
            test_connection "$@"
            ;;
        *)
            log_error "Unknown command: $command"
            show_help
            exit 1
            ;;
    esac
    
    log_success "Deployment script completed successfully"
}

# Run main function with all arguments
main "$@" 